02장 다이오드 기본 회로¶

  • 이름: 홍길동
  • 학번: 2024123456
  • 조: 1

공통 코드¶

In [1]:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import re
import io
from scipy.signal import savgol_filter # 사비츠키-골레이(Savitzky-Golay) 필터
from numpy import nan, inf

from IPython.display import Image

# %matplotlib tk
# %matplotlib inline

def tangent_line(f, x):
    h = 1e-4
    d = (f(x+h) - f(x-h)) / (2*h)
    return lambda t: d*t - d*x + f(x)

def tangent_line_end(f, x):
    h = 1e-4
    d = (f(x) - f(x-h)) / (h)
    return lambda t: d*t - d*x + f(x)

def tangent_line_and_gradient(f, x):
    h = 1e-4
    d = (f(x+h) - f(x-h)) / (2*h)
    return (lambda t: d*t - d*x + f(x)), d

def tangent_line_and_gradient_end(f, x):
    h = 1e-4
    d = (f(x) - f(x-h)) / (h)
    return (lambda t: d*t - d*x + f(x)), d

def derivative(f, x):
    h = 1e-4
    d = (f(x+h) - f(x-h)) / (2*h)
    return d

def get_simulation_result(file_name, start=0, end=-1):
    if end == -1:
        end = None
    else:
        end += 1

    with open(file_name, encoding='cp1252') as data_file:
        lines = data_file.read()
        occurrences = lines.count('Step Information:')
        data_file.seek(0)

        line = data_file.readline()
        labels = re.split(', | ,|\t', line)
        labels = [s.strip().upper() for s in labels]

        data = {}

        if (occurrences == 0):
            for label in labels:
                data[label] = []

            for line in data_file:
                values = re.split(', | ,|\t', line)
                for i in range(len(values)):
                    value = float(values[i]) * 1000
                    data[labels[i]].append(value)

        else:
            labels_all =[]

            lines = data_file.readline() # skip first line starting with 'Step Information:'

            for idx in range(occurrences):
                labels_new = []
                for label in labels:
                    labels_new.append('(%s)@%d' % (label, idx+1))
                labels_all += labels_new

                for label_new in labels_new:
                    data[label_new] = []

                for line in data_file:
                    if (line.startswith('Step Information:')):
                        break
                    values = re.split(', | ,|\t', line)
                    for i in range(len(values)):
                        value = float(values[i]) * 1000
                        data[labels_new[i]].append(value)

            labels = labels_all

        for label in labels:
            data[label] = np.array(data[label][start:end])

    # print("labels = ", end='')
    # print(list(data.keys()))
    for label in list(data.keys()):
        print("data['%s'] : sample number = %d" % (label, len(data[label])))

    return data

def get_oscilloscpoe_result_tektronix(file_name, start=0, end=-1):
    if end == -1:
        end = None
    else:
        end += 1

    df = pd.read_csv(file_name, header=None, encoding='cp1252',low_memory=False)

    label_ri = df.loc[df.iloc[:,0] == 'Source', 1].index
    ci = 0
    data = {}
    data['TIME'] = df.iloc[start:end, 3].to_numpy().astype(float)
    data['TIME'] -= data['TIME'][0]
    for idx in range(df.shape[1]//6):
        label = df.iloc[label_ri, ci+1].item()
        data[label] = df.iloc[start:end,ci+4].to_numpy().astype(float)
        ci += 6

    # print("labels = ", end='')
    # print(list(data.keys()))
    for label in list(data.keys()):
        print("data['%s'] : sample number = %d" % (label, len(data[label])))

    return data

def print_array(label, values):
    print('%s = [' % label, end='')
    for idx, vd in enumerate(values):
        print('{:11.3f}'.format(vd), end='')
        if (idx+1 != len(values)):
            print(', ', end='')
    print(']')

def print_value(label, value):
    print('%s = ' % label, end='')
    print('{:11.3f}'.format(value))

def print_value_to_string(label, value):
    output = io.StringIO()
    print('%s = ' % label, end='', file=output)
    print('{:11.3f}'.format(value), file=output)
    captured = output.getvalue()
    return captured

def draw_plot(xs, ys, label, style_idx, color_idx=-1, marker_num=16, scatter=False, scatter_s=2):
    linestyle  = ['-',          '-',            '-',            '-',            '-',
                  '-',          '-',            '-',            '-',            '-',
                  '-',          '-',            '-',            '-',            '-',
                  '-',          '-',            '-',            '-',            '-',
                  '-',          '-',            '-',            '-',            '-']
    colors     = ['blue',       'green',        'red',          'orange',       'purple',
                  'cyan',       'darkseagreen', 'brown',        'goldenrod',    'darkviolet',
                  'steelblue',  'limegreen',    'tomato',       'tan',          'deeppink',
                  'navy',       'lightgreen',   'indianred',    'khaki',        'rebeccapurple',
                  'slategray',  'forestgreen',  'orangered',    'wheat',        'orchid']
    markers    = ['o',          'v',            '<',            's',            'p',
                  'h',          '*',            'X',            'x',            '^',
                  '>',          'P',            'D',            'H',            'd',
                  '|',          '-',            '4'             '5',            '6',
                  '7',          '8',            '9 ',           '10',           '+']

    if color_idx < 0:
        color_idx = style_idx

    if isinstance(xs, list):
        xs = np.array(xs)
    if isinstance(ys, list):
        ys = np.array(ys)

    if (marker_num == 0):
        selected_markevery = None
        selected_marker = None
    elif not isinstance(xs, np.ndarray):
        selected_markevery = None
        selected_marker = markers[style_idx]
    elif (marker_num > 0):
        markeverys = []
        if xs[0] > xs[-1]:
            first_idx = -1
        else:
            first_idx = 0
        x_step = (xs.max() - xs.min()) / marker_num
        for idx in range(len(markers)):
            x_start = xs.min() + ((x_step / (len(markers) + 1)) * idx)
            marker_list = []
            for j in range(marker_num):
                tmp_array = np.where(xs > (x_start + (x_step * j)))
                if (len(tmp_array[0]) > 0):
                    marker_list.append(tmp_array[0][first_idx])
            markeverys.append(marker_list)

        selected_markevery = markeverys[style_idx]
        selected_marker = markers[style_idx]
    else:
        selected_markevery = None
        selected_marker = markers[style_idx]

    if (scatter):
        plt.scatter(xs, ys, color=colors[color_idx], marker=selected_marker, s=scatter_s, label=label)
    else:
        plt.plot(xs, ys, ls=linestyle[style_idx], color=colors[color_idx], marker=selected_marker, markevery=selected_markevery, label=label)
    if (label != None):
        plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0.)

def set_plot_size(xrate, yrate):
    if (len(set_plot_size.g_plt_figsize) == 0):
        set_plot_size.g_plt_figsize = plt.rcParams["figure.figsize"]
    size = []
    size.append(set_plot_size.g_plt_figsize[0] * xrate)
    size.append(set_plot_size.g_plt_figsize[1] * yrate)
    plt.figure(figsize=size)

set_plot_size.g_plt_figsize = []

실험01 다이오드의 측정 : DMM¶

실험01-01 다이오드 순, 역방향 전압 측정하기¶

실험 방법¶

  • Si 다이오드 (1N4148)
  • Ge 다이오드 (1N270)
  • 전원용 다이오드 (1N4004)
  • 제너 다이오드 (1N5234)
  • LED (빨간색)
  • LED (녹색)
  • LED (흰색)
In [2]:
display(Image("./images/ch02_ep01_01_circuit.png", width=1000))
No description has been provided for this image

실험 결과¶

In [3]:
# 멀티미터 측정 결과가 OL이면 inf로 기록한다.

V_D_S_1N4148_forward_V = 0.564
V_D_S_1N4148_reverse_V = inf

V_D_G_1N270_forward_V = 0.183
V_D_G_1N270_reverse_V = inf

V_D_R_1N4004_forward_V = 0.530
V_D_R_1N4004_reverse_V = inf

V_D_Z_1N5234_forward_V = 0.718
V_D_Z_1N5234_reverse_V = inf

V_D_L_R_forward_V = 1.752
V_D_L_R_reverse_V = inf

V_D_L_G_forward_V = 1.773
V_D_L_G_reverse_V = inf

V_D_L_W_forward_V = inf
V_D_L_W_reverse_V = inf

실험02 다이오드 전압-전류 특성 측정¶

실험02-01 다이오드 전압-전류 특성 측정하기¶

실험 방법¶

  • Vi: 직류 0.4 ~ 10 V
In [4]:
display(Image("./images/ch02_ep02_01_circuit.png", width=400))
No description has been provided for this image

실험 결과¶

제작한 회로¶
In [5]:
display(Image("./data/ch02_ep02_01_result_circuit.jpg", width=1000))
No description has been provided for this image
멀티미터 측정값¶
In [6]:
V_S_V = [  0.400,  0.600,  0.800,  1.000,  2.000,  3.000,  4.000,  5.000,  6.000,  7.000,  8.000,  9.000, 10.000]

V_I_V = [  0.40 ,  0.60 ,  0.80 ,  1.01 ,  2.02 ,  3.02 ,  4.02 ,  5.02 ,  6.03 ,  7.04 ,  8.06 ,  9.06 ,  10.07]
V_D_V = [  0.395,  0.497,  0.541,  0.564,  0.620,  0.646,  0.663,  0.676,  0.687,  0.695,  0.703,  0.710,  0.716]

결과 분석¶

In [7]:
# 저항 R1의 크기와, 이 저항에 걸리는 전압값을 사용해 다이오드, D1에 흐르는 전류값을 계산한다.
R1_ohm = 1000

V_D_V = np.array(V_D_V)
V_I_V = np.array(V_I_V)

I_D_A = ((V_I_V - V_D_V) / R1_ohm)
I_D_mA = I_D_A * 1000
print_array('I_D_mA', I_D_mA)

# 다이오드의 I-V 특성 곡선을 그린다.
plt.xlabel('V_D_V')
plt.ylabel('I_D_mA')
plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.axvline(0.7, color='green')
plt.xlim(-0.08,  0.8)
plt.ylim(-1.0, 10.0)
plt.plot(V_D_V, I_D_mA, 'b.-')
plt.show()
I_D_mA = [      0.005,       0.103,       0.259,       0.446,       1.400,       2.374,       3.357,       4.344,       5.343,       6.345,       7.357,       8.350,       9.354]
No description has been provided for this image
In [8]:
# 다이오드 특성 곡선에서 정전압 등가모델용 V_cut_in을 구한다.
V_cut_in_V = 0.7

print("V_cut_in_V = {:8.3f}".format(V_cut_in_V))
V_cut_in_V =    0.700
In [9]:
# 다이오드 특성 곡선에서 부분선형 등가모델용 V_cut_in과 r_D을 구한다.

i1 = 7
i2 = 12

xs = V_D_V
ys = I_D_mA

m = (ys[i2] - ys[i1]) / (xs[i2] - xs[i1])
b = ys[i2] - m * xs[i2]
tf = lambda x: m * x + b
gradient = m
txs = np.arange(0.6, 0.8, 0.01)
tys = tf(txs)

V_cut_in_V = np.interp(0.0, tys, txs)
r_D__V_div_mA = 1. / gradient
r_D_ohm = r_D__V_div_mA * 1000.

plt.xlabel('V_D_V')
plt.ylabel('I_D_mA')
plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.xlim(-0.08,  0.8)
plt.ylim(-1.0, 10.0)
plt.plot(xs, ys, 'b.-')
plt.plot(txs, tys, 'g-')
plt.scatter(V_cut_in_V, 0)
plt.scatter(xs[i1], ys[i1])
plt.scatter(xs[i2], ys[i2])
plt.text(V_cut_in_V-0.2, 0-1.0, print_value_to_string('V_cut_in_V', V_cut_in_V))
plt.show()

print("Point A: {}, {}, {}".format(V_S_V[i1], xs[i1], ys[i1]))
print("Point B: {}, {}, {}".format(V_S_V[i2], xs[i2], ys[i2]))
print()
print("r_D_ohm    = {:8.3f}".format(r_D_ohm))
print("V_cut_in_V = {:8.3f}".format(V_cut_in_V))
No description has been provided for this image
Point A: 5.0, 0.676, 4.343999999999999
Point B: 10.0, 0.716, 9.354000000000001

r_D_ohm    =    7.984
V_cut_in_V =    0.641

실험03 리미터 회로¶

실험03-01 리미터 만들기¶

실험 방법¶

  • 다이오드:
    • Si 다이오드 (1N4148)
    • Ge 다이오드 (1N270)
    • 전원용 다이오드 (1N4004)
    • 제너 다이오드 (1N5234)
    • LED (빨간색)
    • LED (녹색)
    • LED (흰색)
In [10]:
display(Image("./images/ch02_ep03_01_circuit.png", width=400))
No description has been provided for this image

실험 결과¶

제작한 회로¶
In [11]:
display(Image("./data/ch02_ep03_01_result_circuit.jpg", width=1000))
No description has been provided for this image
멀티미터 측정값¶
In [12]:
V_D_S_1N4148_V = 0.677

V_D_G_1N270_V = 0.263

V_D_R_1N4004_V = 0.640

V_D_Z_1N5234_V = 0.775

V_D_L_R_V = 1.922

V_D_L_G_V = 1.952

V_D_L_W_V = 2.649

실험04 피크검출기 회로¶

실험04-01 피크검출기 만들기¶

실험 방법¶

  • 다이오드: 1N4148
  • Vi: 정현파, 주파수 1 kHz, 크기 8 ~ 12 Vpp
In [13]:
display(Image("./images/ch02_ep04_01_circuit.png", width=400))
No description has been provided for this image

실험 결과¶

제작한 회로¶
In [14]:
display(Image("./data/ch02_ep04_01_result_circuit.jpg", width=1000))
No description has been provided for this image
오실로스코프 화면¶
In [15]:
# 8 Vpp
display(Image("./data/ch02_ep04_02_result_08vpp.png", width=600))

# 10 Vpp
display(Image("./data/ch02_ep04_03_result_10vpp.png", width=600))

# 12 Vpp
display(Image("./data/ch02_ep04_04_result_12vpp.png", width=600))

# 8 Vpp
display(Image("./data/ch02_ep04_05_result_08vpp.png", width=600))
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image
No description has been provided for this image

결과 분석¶

In [16]:
# 실험 결과 파일을 읽는다.
data_02_08vpp = get_oscilloscpoe_result_tektronix('./data/ch02_ep04_02_result_08vpp.csv')
data_03_10vpp = get_oscilloscpoe_result_tektronix('./data/ch02_ep04_03_result_10vpp.csv')
data_04_12vpp = get_oscilloscpoe_result_tektronix('./data/ch02_ep04_04_result_12vpp.csv')
data_05_08vpp = get_oscilloscpoe_result_tektronix('./data/ch02_ep04_05_result_08vpp.csv')

# 실험 결과에서 시간, 입력 전압, 출력 전압을 가져온다.
times_02_08vpp = data_02_08vpp['TIME']
vins_02_08vpp  = data_02_08vpp['Sample CH1']
vouts_02_08vpp = data_02_08vpp['Sample CH2']

times_03_10vpp = data_03_10vpp['TIME']
vins_03_10vpp  = data_03_10vpp['Sample CH1']
vouts_03_10vpp = data_03_10vpp['Sample CH2']

times_04_12vpp = data_04_12vpp['TIME']
vins_04_12vpp  = data_04_12vpp['Sample CH1']
vouts_04_12vpp = data_04_12vpp['Sample CH2']

times_05_08vpp = data_05_08vpp['TIME']
vins_05_08vpp  = data_05_08vpp['Sample CH1']
vouts_05_08vpp = data_05_08vpp['Sample CH2']

# 필터를 적용해 잡음을 줄인다.
vins_02_08vpp = savgol_filter(vins_02_08vpp, 100, 2)
vouts_02_08vpp = savgol_filter(vouts_02_08vpp, 100, 2)

vins_03_10vpp = savgol_filter(vins_03_10vpp, 100, 2)
vouts_03_10vpp = savgol_filter(vouts_03_10vpp, 100, 2)

vins_04_12vpp = savgol_filter(vins_04_12vpp, 100, 2)
vouts_04_12vpp = savgol_filter(vouts_04_12vpp, 100, 2)

vins_05_08vpp = savgol_filter(vins_05_08vpp, 100, 2)
vouts_05_08vpp = savgol_filter(vouts_05_08vpp, 100, 2)

# 시간을 x축, 전압들을 y축으로 하는 그래프를 그리고, v_out을 구한다.
plt.title("02_08vpp")
plt.xlabel('TIME_s')
plt.ylabel('V_V')
plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.ylim((-7, 7))
draw_plot(times_02_08vpp, vins_02_08vpp, 'V(IN)', 0)
draw_plot(times_02_08vpp, vouts_02_08vpp, 'V(OUT)', 1)
plt.show()

V_OUT_mean_V_02_08vpp = vouts_02_08vpp.mean()
print_value("V_OUT_mean_V_02_08vpp", V_OUT_mean_V_02_08vpp)
print()

plt.title("03_10vpp")
plt.xlabel('TIME_s')
plt.ylabel('V_V')
plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.ylim((-7, 7))
draw_plot(times_03_10vpp, vins_03_10vpp, 'V(IN)', 0)
draw_plot(times_03_10vpp, vouts_03_10vpp, 'V(OUT)', 1)
plt.show()


V_OUT_mean_V_03_10vpp = vouts_03_10vpp.mean()
print_value("V_OUT_mean_V_03_10vpp", V_OUT_mean_V_03_10vpp)
print()

plt.title("04_12vpp")
plt.xlabel('TIME_s')
plt.ylabel('V_V')
plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.ylim((-7, 7))
draw_plot(times_04_12vpp, vins_04_12vpp, 'V(IN)', 0)
draw_plot(times_04_12vpp, vouts_04_12vpp, 'V(OUT)', 1)
plt.show()


V_OUT_mean_V_04_12vpp = vouts_04_12vpp.mean()
print_value("V_OUT_mean_V_04_12vpp", V_OUT_mean_V_04_12vpp)
print()

plt.title("05_08vpp")
plt.xlabel('TIME_s')
plt.ylabel('V_V')
plt.axhline(0, color='black')
plt.axvline(0, color='black')
plt.ylim((-7, 7))
draw_plot(times_05_08vpp, vins_05_08vpp, 'V(IN)', 0)
draw_plot(times_05_08vpp, vouts_05_08vpp, 'V(OUT)', 1)
plt.show()

V_OUT_mean_V_05_08vpp = vouts_05_08vpp.mean()
print_value("V_OUT_mean_V_05_08vpp", V_OUT_mean_V_05_08vpp)
print()
data['TIME'] : sample number = 5208
data['Glitch Capture CH1'] : sample number = 5208
data['Sample CH1'] : sample number = 5208
data['Glitch Capture CH2'] : sample number = 5208
data['Sample CH2'] : sample number = 5208
data['TIME'] : sample number = 5208
data['Glitch Capture CH1'] : sample number = 5208
data['Sample CH1'] : sample number = 5208
data['Glitch Capture CH2'] : sample number = 5208
data['Sample CH2'] : sample number = 5208
data['TIME'] : sample number = 5208
data['Glitch Capture CH1'] : sample number = 5208
data['Sample CH1'] : sample number = 5208
data['Glitch Capture CH2'] : sample number = 5208
data['Sample CH2'] : sample number = 5208
data['TIME'] : sample number = 5208
data['Glitch Capture CH1'] : sample number = 5208
data['Sample CH1'] : sample number = 5208
data['Glitch Capture CH2'] : sample number = 5208
data['Sample CH2'] : sample number = 5208
No description has been provided for this image
V_OUT_mean_V_02_08vpp =       3.601

No description has been provided for this image
V_OUT_mean_V_03_10vpp =       4.619

No description has been provided for this image
V_OUT_mean_V_04_12vpp =       5.595

No description has been provided for this image
V_OUT_mean_V_05_08vpp =       5.502


실험05 정류기 회로¶

실험05-01 정류기 만들기¶

실험 방법¶

  • 다이오드: 1N4004
  • Vi: 정현파, 주파수 1 kHz, 크기 8 Vpp
In [17]:
display(Image("./images/ch02_ep05_01_circuit.png", width=400))
No description has been provided for this image

실험 결과¶

제작한 회로¶
In [18]:
display(Image("./data/ch02_ep05_01_result_circuit.jpg", width=1000))
No description has been provided for this image
오실로스코프 화면¶
In [19]:
display(Image("./data/ch02_ep05_02_result.png", width=600))
display(Image("./data/ch02_ep05_03_result_xy.png", width=600))
No description has been provided for this image
No description has been provided for this image

결과 분석¶

In [20]:
# 실험 결과 파일을 읽는다.
data = get_oscilloscpoe_result_tektronix('./data/ch02_ep05_02_result.csv')

# 실험 결과에서 시간, 입력 전압, 출력 전압을 가져온다.
times = data['TIME']
vins = data['Sample CH1']
vouts = data['Sample CH2']

# 필터를 적용해 잡음을 줄인다.
vins = savgol_filter(vins, 100, 2)
vouts = savgol_filter(vouts, 100, 2)

# 시간을 x축, 전압들을 y축으로 하는 그래프를 그린다.
plt.xlabel('TIME_s')
plt.ylabel('V_V')
plt.axhline(0, color='black')
plt.axvline(0, color='black')
draw_plot(times, vins, 'V(IN)', 0)
draw_plot(times, vouts, 'V(OUT)', 1)
plt.show()

# 입력 전압을 x축, 출력 전압을 y축으로 하는 그래프를 그린다.
plt.xlabel('V_IN_V')
plt.ylabel('V_OUT_V')
plt.axhline(0, color='black')
plt.axvline(0, color='black')
draw_plot(vins, vouts, "XY", 0)
plt.show()
data['TIME'] : sample number = 5208
data['Glitch Capture CH1'] : sample number = 5208
data['Sample CH1'] : sample number = 5208
data['Glitch Capture CH2'] : sample number = 5208
data['Sample CH2'] : sample number = 5208
No description has been provided for this image
No description has been provided for this image